SimpleController_UsingActions.cs (3839B)
1 using System.Collections; 2 using UnityEngine.InputSystem; 3 using UnityEngine; 4 using UnityEngine.InputSystem.Interactions; 5 6 // Using simple actions with callbacks. 7 public class SimpleController_UsingActions : MonoBehaviour 8 { 9 public float moveSpeed; 10 public float rotateSpeed; 11 public float burstSpeed; 12 public GameObject projectile; 13 14 public InputAction moveAction; 15 public InputAction lookAction; 16 public InputAction fireAction; 17 18 private bool m_Charging; 19 20 private Vector2 m_Rotation; 21 22 public void Awake() 23 { 24 // We could use `fireAction.triggered` in Update() but that makes it more difficult to 25 // implement the charging mechanism. So instead we use the `started`, `performed`, and 26 // `canceled` callbacks to run the firing logic right from within the action. 27 28 fireAction.performed += 29 ctx => 30 { 31 if (ctx.interaction is SlowTapInteraction) 32 { 33 StartCoroutine(BurstFire((int)(ctx.duration * burstSpeed))); 34 } 35 else 36 { 37 Fire(); 38 } 39 m_Charging = false; 40 }; 41 fireAction.started += 42 ctx => 43 { 44 if (ctx.interaction is SlowTapInteraction) 45 m_Charging = true; 46 }; 47 fireAction.canceled += 48 ctx => 49 { 50 m_Charging = false; 51 }; 52 } 53 54 public void OnEnable() 55 { 56 moveAction.Enable(); 57 lookAction.Enable(); 58 fireAction.Enable(); 59 } 60 61 public void OnDisable() 62 { 63 moveAction.Disable(); 64 lookAction.Disable(); 65 fireAction.Disable(); 66 } 67 68 public void OnGUI() 69 { 70 if (m_Charging) 71 GUI.Label(new Rect(100, 100, 200, 100), "Charging..."); 72 } 73 74 public void Update() 75 { 76 var look = lookAction.ReadValue<Vector2>(); 77 var move = moveAction.ReadValue<Vector2>(); 78 79 // Update orientation first, then move. Otherwise move orientation will lag 80 // behind by one frame. 81 Look(look); 82 Move(move); 83 } 84 85 private void Move(Vector2 direction) 86 { 87 if (direction.sqrMagnitude < 0.01) 88 return; 89 var scaledMoveSpeed = moveSpeed * Time.deltaTime; 90 // For simplicity's sake, we just keep movement in a single plane here. Rotate 91 // direction according to world Y rotation of player. 92 var move = Quaternion.Euler(0, transform.eulerAngles.y, 0) * new Vector3(direction.x, 0, direction.y); 93 transform.position += move * scaledMoveSpeed; 94 } 95 96 private void Look(Vector2 rotate) 97 { 98 if (rotate.sqrMagnitude < 0.01) 99 return; 100 var scaledRotateSpeed = rotateSpeed * Time.deltaTime; 101 m_Rotation.y += rotate.x * scaledRotateSpeed; 102 m_Rotation.x = Mathf.Clamp(m_Rotation.x - rotate.y * scaledRotateSpeed, -89, 89); 103 transform.localEulerAngles = m_Rotation; 104 } 105 106 private IEnumerator BurstFire(int burstAmount) 107 { 108 for (var i = 0; i < burstAmount; ++i) 109 { 110 Fire(); 111 yield return new WaitForSeconds(0.1f); 112 } 113 } 114 115 private void Fire() 116 { 117 var transform = this.transform; 118 var newProjectile = Instantiate(projectile); 119 newProjectile.transform.position = transform.position + transform.forward * 0.6f; 120 newProjectile.transform.rotation = transform.rotation; 121 var size = 1; 122 newProjectile.transform.localScale *= size; 123 newProjectile.GetComponent<Rigidbody>().mass = Mathf.Pow(size, 3); 124 newProjectile.GetComponent<Rigidbody>().AddForce(transform.forward * 20f, ForceMode.Impulse); 125 newProjectile.GetComponent<MeshRenderer>().material.color = 126 new Color(Random.value, Random.value, Random.value, 1.0f); 127 } 128 }